/*
 * ActionMgr.cpp
 *
 *  Created on: 2012-9-4
 *      Author: yangentao@gmail.com
 */

#include "ActionManager.h"

ITextReplacable::~ITextReplacable() {
}

Action::Action(int from_, int len_, String newText_) {
	from = from_;
	length = len_;
	newText = newText_;
	groupId = 0;
}

void Action::dump() {
	cerr << "from=" << from;
	cerr << ", lenth=" << length;
	cerr << ", oldText=[" << oldText << "]";
	cerr << ", newText=[" << newText << "]" << endl;

}

ActionManager::ActionManager(ITextReplacable* textReplacable_) {
	groupId = 0;
	textReplacable = textReplacable_;
}
void ActionManager::setTextReplacable(ITextReplacable* textReplacable_) {
	textReplacable = textReplacable_;
}
void ActionManager::performAction(Action& action) {
	action.oldText = textReplacable->textReplace(action.from, action.length, action.newText);
}
void ActionManager::performUndo(Action& action) {
	textReplacable->textReplace(action.from, action.newText.length(), action.oldText);

}
vector<Action> ActionManager::popGroup(Stack<Action>& s) {
	vector<Action> v;
	while (s.size()) {
		Action a = s.top();// can not be Action& !!!
		if (v.empty()) {
			s.pop();
			v.push_back(a);
		} else {
			if (a.groupId && a.groupId == v.front().groupId) {
				s.pop();
				v.push_back(a);
			} else {
				break;
			}
		}
	}
	return v;
}
void ActionManager::beginGroup() {
	groupId = getTimeTick();
}
void ActionManager::endGroup() {
	groupId = 0;
}
void ActionManager::doAction(Action action) {
	action.groupId = groupId;
	performAction(action);
	undos.push(action);
	redos.clear();
}
void ActionManager::undo() {
	vector<Action> v = popGroup(undos);
	for (int i = 0; i < v.size(); ++i) {
		Action& ac = v[i];
		performUndo(ac);
		redos.push(ac);
	}
}
void ActionManager::redo() {
//		assert(redos.size());
	vector<Action> v = popGroup(redos);
	for (int i = 0; i < v.size(); ++i) {
		Action& ac = v[i];
		performAction(ac);
		undos.push(ac);
	}
}
bool ActionManager::canUndo() {
	return !undos.empty();
}
bool ActionManager::canRedo() {
	return !redos.empty();
}

void ActionManager::clear() {
	undos.clear();
	redos.clear();
	groupId = 0;
}

